package cn.reone.mbt.ui;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatEditText;
import android.support.v7.widget.AppCompatTextView;
import android.text.method.ScrollingMovementMethod;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import android.widget.Toast;

import com.orhanobut.logger.Logger;

import java.io.IOException;
import java.util.UUID;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.reone.mbt.R;
import cn.reone.mbt.connect.ConnectedThread;

public class ServerActivity extends AppCompatActivity {

    private final UUID MY_UUID = UUID.nameUUIDFromBytes("cn.reone.mbt".getBytes());
    @BindView(R.id.info_show)
    AppCompatTextView infoShow;
    @BindView(R.id.socket_show)
    AppCompatTextView socketShow;
    @BindView(R.id.socket_send)
    AppCompatEditText socketSend;
    private BluetoothAdapter mBluetoothAdapter;
    private ServerThread mServerThread;
    private BluetoothSocket mSocket;
    private ConnectedThread mConnectedThread;
    private BluetoothDevice remoteDevice;
    private StringBuffer msgInfo = new StringBuffer();
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == ConnectedThread.MESSAGE_READ) {
                if (msg.obj!=null && msg.obj instanceof byte[]) {
                    msgInfo.append("\nmsg: " + new String((byte[]) msg.obj));
                }
                socketShow.setText(msgInfo);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server);
        ButterKnife.bind(this);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        updateInfo();
        socketShow.setMovementMethod(ScrollingMovementMethod.getInstance());
        socketSend.setImeOptions(EditorInfo.IME_ACTION_SEND);
        socketSend.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                mConnectedThread.write(socketSend.getText().toString().getBytes());
                socketSend.setText("");
                socketSend.clearFocus();
                return false;
            }
        });
    }

    public void talk(final String str) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(ServerActivity.this, str, Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void updateInfo() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                StringBuffer sb = new StringBuffer();
                sb.append("name : " + mBluetoothAdapter.getName()
                        + "\naddress : " + mBluetoothAdapter.getAddress()
                        + "\nstate : " + mBluetoothAdapter.getState()
                        + "\nmode : " + mBluetoothAdapter.getScanMode()
                        + "\nisEnabled : " + mBluetoothAdapter.isEnabled()
                        + "\nisDiscovering : " + mBluetoothAdapter.isDiscovering()
                );
                if (remoteDevice != null) {
                    sb.append("\nremote : " + remoteDevice.getName() + "\n->" + remoteDevice.getAddress());
                }
                infoShow.setText(sb.toString());
            }
        });
    }

    @OnClick(R.id.start_server)
    public void startServer() {
        mServerThread = new ServerThread();
        mServerThread.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mServerThread != null) {
            mServerThread.cancel();
        }
        if (mConnectedThread != null) {
            mConnectedThread.cancel();
        }
    }

    class ServerThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public ServerThread() {
            // Use a temporary object that is later assigned to mmServerSocket,
            // because mmServerSocket is final
            BluetoothServerSocket tmp = null;
            try {
                // MY_UUID is the app's UUID string, also used by the client code
                String name = "server-" + mBluetoothAdapter.getAddress();
                Logger.d("socket name : " + name + "\nsocket uuid : " + MY_UUID);
                tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(name, MY_UUID);
            } catch (IOException e) {
            }
            mmServerSocket = tmp;
        }

        public void run() {
            BluetoothSocket socket = null;
            // Keep listening until exception occurs or a socket is returned
            while (true) {
                try {
                    talk("等待连接");
                    socket = mmServerSocket.accept();
                    remoteDevice = socket.getRemoteDevice();
                    updateInfo();
                    talk("已接收到连接: " + remoteDevice.getAddress());
                } catch (IOException e) {
                    break;
                }
                // 这将释放服务器套接字及其所有资源，但不会关闭 accept() 所返回的已连接的 BluetoothSocket。
                // 与 TCP/IP 不同，RFCOMM 一次只允许每个通道有一个已连接的客户端，因此大多数情况下，
                // 在接受已连接的套接字后立即在 BluetoothServerSocket 上调用 close() 是行得通的。
                if (socket != null) {
                    // Do work to manage the connection (in a separate thread)
                    manageConnectedSocket(socket);
                    try {
                        mmServerSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }

        /**
         * Will cancel the listening socket, and cause the thread to finish
         */
        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) {
            }
        }
    }

    /**
     * 用来处理线程中获取到的socket,此socket可以用来数据传输
     *
     * @param socket
     */
    private void manageConnectedSocket(BluetoothSocket socket) {
        mSocket = socket;
        mConnectedThread = new ConnectedThread(mSocket, mHandler);
        mConnectedThread.start();
        mConnectedThread.write("hallo,here is server".getBytes());
    }
}
